package com.gem.netty.message.swap;

import com.gem.entity.Card;
import com.gem.entity.Game;
import com.gem.enums.ClientMessageType;
import com.gem.enums.GameRoundStageType;
import com.gem.enums.GemType;
import com.gem.enums.MessageColorType;
import com.gem.factory.card.CardBaseFactory;
import com.gem.factory.game.GameFactory;
import com.gem.holder.ThreadLocalFactory;
import com.gem.netty.entity.CardInfo;
import com.gem.netty.entity.ClientContent;
import com.gem.netty.entity.CurrentUser;
import com.gem.utils.R;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Author: Xhy
 * CreateTime: 2022-12-14 21:42
 */
public class GetCard extends AbstractSwapBase {

    @Override
    protected R isVerify(ClientContent context) {
        CardInfo cardInfo = context.getContent().getCardInfo();

        // 是否为空
        if (cardInfo == null){
            return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("非法操作").type(ClientMessageType.GET_CARD.type);
        }
        Game game = GameFactory.get(context.getRoomId());
        Map<Integer, Integer> userUseGems = cardInfo.getGems();

        CurrentUser user = game.getUsers().get(game.getCurrentIndex());

        // 玩家是否使用黄金替宝石
        Map<Integer, Integer> replaceGems = cardInfo.getReplaceGems();
        List<CardInfo> userTsCards = user.getTSCards();
        if (replaceGems.size() > 0){
            // 玩家使用黄金替宝石后，玩家需要选择一张牌丢弃
            CardInfo discardCardInfo = context.getContent().getDiscardCardInfo();
            if (discardCardInfo!=null){
                boolean f = false;
                // 校验玩家是否丢弃的是压住牌库中的牌
                Iterator<CardInfo> cardInfoIterator = userTsCards.iterator();
                Integer no = null;
                while (cardInfoIterator.hasNext()){
                    CardInfo next = cardInfoIterator.next();
                    if (next.getNo() == discardCardInfo.getNo()){
                        no = next.getNo();
                        // 玩家丢弃卡牌
                        cardInfoIterator.remove();
                        f = true;
                        break;
                    }
                }

                if (!f){

                    return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("只能选择自己牌库中的牌").type(ClientMessageType.GET_CARD.type);
                }

                String roomId = context.getRoomId();
                // 游戏牌库添加卡牌
                Card card = Card.getCard(no);
                CardBaseFactory.add(roomId,card);
            }
            boolean isTsCard = false;
            for (CardInfo userTsCard : userTsCards) {
                isTsCard = userTsCard.getNo() == cardInfo.getNo();
            }
            ThreadLocalFactory.put("isTsCard", isTsCard);
            // 玩家是否拥有足够的黄金
            AtomicInteger gemsNumber = new AtomicInteger(0);
            replaceGems.forEach((k,number)->{
                gemsNumber.getAndAdd(number);
            });
            int userGoldGem = user.getGems().get(GemType.GOLD.type);
            userGoldGem -= userTsCards.size(); // 计算出真实可听宝石的数量
            if (isTsCard) userGoldGem++;
            if (userGoldGem < gemsNumber.get()){

                return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("你没有足够的黄金").type(ClientMessageType.GET_CARD.type);
            }
            // 把替换的宝石添加至 gems
            replaceGems.forEach((k,number)->{
                if (userUseGems.containsKey(k)){
                    userUseGems.put(k,userUseGems.get(k)+number);
                }else {
                    userUseGems.put(k,number);
                }
            });

        }


        // 换取的卡牌只能是场下的或者自己压住的牌库
        Integer cardNo = cardInfo.getNo();
        List<Card> cardList = game.getShowCards().get(cardInfo.getType());
        for (Card card : cardList) {
            if (card.getNo() == cardNo){
                return R.ok();

            }
        }
        for (CardInfo tsCard : userTsCards) {
            if (tsCard.getNo() == cardNo){
                return R.ok();
            }
        }
        return R.error().data("color",MessageColorType.SYSTEM_MESSAGE.type).message("你不能换别人的牌哦").type(ClientMessageType.GET_CARD.type);
    }

    @Override
    protected R isStock(ClientContent context) {
        Game game = GameFactory.get(context.getRoomId());
        CardInfo cardInfo = context.getContent().getCardInfo();
        int i = 0;
        List<Card> cardList = game.getShowCards().get(cardInfo.getType());
        CurrentUser user = game.getUsers().get(game.getCurrentIndex());
        // 校验场上是否有该牌 || 用户自己压住的牌
        for (; i <cardList.size(); i++) {
            if (cardList.get(i).getNo() == cardInfo.getNo() || existTsCard(user.getTSCards(),cardInfo.getNo())){
                return R.ok();
            }
        }
        return R.error();
    }
    private boolean existTsCard(List<CardInfo> tsCards, Integer no) {
        for (CardInfo tsCard : tsCards) {
            if (tsCard.getNo() == no){
                return true;
            }
        }
        return false;
    }
    @Override
    public R isOwnNobility(ClientContent content) {
        return R.ok();
    }

    @Override
    protected R isSwap(ClientContent context) {
        Game game = GameFactory.get(context.getRoomId());
        CurrentUser user = game.getUsers().get(game.getCurrentIndex());
        CardInfo cardInfo = context.getContent().getCardInfo();
        // 卡牌所需宝石
        Map<Integer, Integer> swapCardNeedGems =  Card.getCardGems(cardInfo.getNo());
        // 获取用户使用的宝石
        Map<Integer, Integer> userUseGems = cardInfo.getGems();
        // 获取用户使用的buff
        Map<Integer, Integer> userUserBuff = cardInfo.getGemCards();
        // 获取用户使用的听宝石
        Map<Integer, Integer> userUseTingGem = cardInfo.getReplaceGems();
        // 用户记录更新用户手里宝石
        Map<Integer,Integer> temp = new HashMap<>();
        // 用户自己的宝石
        TreeMap<Integer, Integer> userOwnGem = user.getGems();
        // 默认放行
        AtomicBoolean flag = new AtomicBoolean(false);
        swapCardNeedGems.forEach((k,v)->{
            int gemNum =  (userUseGems != null && userUseGems.containsKey(k)) ? userUseGems.get(k) : 0 ;
            int cardNum = (userUserBuff != null && userUserBuff.containsKey(k)) ? userUserBuff.get(k) : 0 ;
            int tingGem = (userUseTingGem != null && userUseTingGem.containsKey(k)) ? userUseTingGem.get(k) : 0 ;
            int ownGems = gemNum + cardNum;
            int needGems = swapCardNeedGems.get(k);

            if (!trySwapCard(ownGems,needGems)){
                // 退回黄金宝石
                Map<Integer, Integer> replaceGems = cardInfo.getReplaceGems();
                AtomicInteger i = new AtomicInteger(0);
                replaceGems.forEach((k1,v1)->{
                    userOwnGem.put(k1,userOwnGem.get(k1)-v1);
                    i.getAndAdd(v1);
                });
                userOwnGem.put(GemType.GOLD.type,userOwnGem.get(GemType.GOLD.type)+i.get());
                flag.set(true);
                return;
            }
            // 使用buff > 使用的宝石 ? 使用的宝石 : 使用的buff
            int t = cardNum > needGems ? needGems : cardNum;
            temp.put(k,needGems - t - tingGem);
        });
        if (flag.get()){
            return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("换不了卡牌,宝石不够").type(ClientMessageType.GET_CARD.type);
        }
        if (!flag.get()){
            // 用户宝石减少
            temp.forEach((k,v)->{
                Integer gem = (userOwnGem.get(k)==null)?0:userOwnGem.get(k);
                userOwnGem.put(k,gem-v);
            });

            // 用户黄金减少(使用黄金)
            Map<Integer, Integer> replaceGems = cardInfo.getReplaceGems();
            if (replaceGems.size() > 0){
                AtomicInteger number = new AtomicInteger(0);
                replaceGems.forEach((k,v)->{
                    number.getAndAdd(v);
                });
                Object tsCard = ThreadLocalFactory.get("isTsCard");
                Boolean isTsCard = false;
                if (tsCard instanceof Boolean){
                    isTsCard = (Boolean) tsCard;
                }
                if(isTsCard){
                    number.getAndDecrement();
                }

                userOwnGem.put(GemType.GOLD.type,userOwnGem.get(GemType.GOLD.type) - number.get());
            }
        }
        return R.ok();
    }
    private boolean trySwapCard(int ownGems,int needGems){
        return ownGems - needGems >=0;
    }

    @Override
    protected R isSwapCardOrGetGemRound(ClientContent content) {
        Game game = GameFactory.get(content.getRoomId());
        CurrentUser user = game.getUsers().get(game.getCurrentIndex());
        if (user.getState() != GameRoundStageType.SWAP_CARD.type){
            return R.error().data("color", MessageColorType.SYSTEM_MESSAGE.type).message("不是换牌回合").type(ClientMessageType.GET_CARD.type);
        }
        return R.ok();
    }
}
